package com.linkoog.devtools.code_generator.wizard.generate.database.template.tree;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/**
 * 拥有复选框的树形节点
 */
@SuppressWarnings("serial")
public class CheckBoxTreeNode extends DefaultMutableTreeNode {

    protected boolean selected;

    protected boolean childrenAllSelected;

    public CheckBoxTreeNode() {
        this(null);
    }

    public CheckBoxTreeNode(Object userObject) {
        this(userObject, true, false);
    }

    public CheckBoxTreeNode(Object userObject, boolean allowsChildren, boolean selected) {
        super(userObject, allowsChildren);
        this.selected = selected;
    }

    public boolean isSelected() {
        return selected;
    }

    private static void recursionParentSelected(CheckBoxTreeNode currentNode){
        if (currentNode == null){
            return;
        }

        CheckBoxTreeNode pNode = (CheckBoxTreeNode) currentNode.parent;
        if (pNode != null) {
            boolean hasUnCheckedChild = false;
            boolean hasCheckedChild = false;
            Vector<TreeNode> siblings = pNode.children;
            for (TreeNode treeNode : siblings) {
                CheckBoxTreeNode sibling = (CheckBoxTreeNode)treeNode;
                if (sibling.isSelected()){
                    hasCheckedChild = true;
                }else {
                    hasUnCheckedChild = true;
                }
            }

            pNode.selected = hasCheckedChild;
            pNode.childrenAllSelected = hasCheckedChild && !hasUnCheckedChild;

            recursionParentSelected(pNode);
        }
    }

    private void recursionChildSelected(CheckBoxTreeNode currentNode, boolean selected){
        if (currentNode == null){
            return;
        }

        if (currentNode.children == null) {
            return;
        }

        for (Object obj : currentNode.children) {
            CheckBoxTreeNode node = (CheckBoxTreeNode) obj;
            node.selected = selected;
            node.childrenAllSelected = selected;
            recursionChildSelected(node, selected);
        }
    }


    public void setSelected(boolean selected){
        this.selected = selected;
        this.childrenAllSelected = selected;

        recursionChildSelected(this, selected);
        recursionParentSelected(this);
    }


    public static void main(String[] args) {
        CheckBoxTreeNode root = new CheckBoxTreeNode("000-001");

        CheckBoxTreeNode node1_1 = new CheckBoxTreeNode("111-001");
        CheckBoxTreeNode node1_2 = new CheckBoxTreeNode("111-002");
        CheckBoxTreeNode node1_3 = new CheckBoxTreeNode("111-003");
        CheckBoxTreeNode node1_4 = new CheckBoxTreeNode("111-004");
        root.add(node1_1);
        root.add(node1_2);
        root.add(node1_3);
        root.add(node1_4);


        CheckBoxTreeNode node2_1 = new CheckBoxTreeNode("222-001");
        CheckBoxTreeNode node2_2 = new CheckBoxTreeNode("222-002");
        CheckBoxTreeNode node2_3 = new CheckBoxTreeNode("222-003");
        CheckBoxTreeNode node2_4 = new CheckBoxTreeNode("222-004");
        node1_1.add(node2_1);
        node1_1.add(node2_2);
        node1_1.add(node2_3);
        node1_2.add(node2_4);


        CheckBoxTreeNode node3_1 = new CheckBoxTreeNode("333-001");
        CheckBoxTreeNode node3_2 = new CheckBoxTreeNode("333-002");
        CheckBoxTreeNode node3_3 = new CheckBoxTreeNode("333-003");
        CheckBoxTreeNode node3_4 = new CheckBoxTreeNode("333-004");
        node2_1.add(node3_1);
        node2_1.add(node3_2);
        node2_1.add(node3_3);
        node2_1.add(node3_4);


        CheckBoxTreeNode node4_1 = new CheckBoxTreeNode("444-001");
        CheckBoxTreeNode node4_2 = new CheckBoxTreeNode("444-002");
        CheckBoxTreeNode node4_3 = new CheckBoxTreeNode("444-003");
        CheckBoxTreeNode node4_4 = new CheckBoxTreeNode("444-004");
        node3_1.add(node4_1);
        node3_1.add(node4_2);
        node3_1.add(node4_3);
        node3_1.add(node4_4);

        node4_3.selected = true;
        recursionParentSelected(node4_3);

        System.out.println(root);

    }










    public void setSelected1(boolean selected) {
        this.selected = selected;
        if (selected) {
            this.childrenAllSelected = true;
            // 如果选中，则将其所有的子结点都选中
            if (children != null) {
                for (Object obj : children) {
                    CheckBoxTreeNode node = (CheckBoxTreeNode) obj;
                    if (!node.isSelected()) {
                        node.setSelected(true);
                    }
                }
            }

            // 向上检查，如果父结点的所有子结点都被选中，那么将父结点也选中
            CheckBoxTreeNode pNode = (CheckBoxTreeNode) parent;
            // 开始检查pNode的所有子节点是否都被选中
            if (pNode != null) {
                Vector<TreeNode> siblings = pNode.children;
                int index = 0;
                boolean childrenAllSelected = true;
                for (; index < pNode.children.size(); ++index) {
                    CheckBoxTreeNode siblingNode = (CheckBoxTreeNode)siblings.get(index);
                    if (!siblingNode.isSelected()) {
                        childrenAllSelected = false;
                        break;
                    }
                }

                pNode.setSelected(true);
                pNode.childrenAllSelected = childrenAllSelected;
            }
        } else {
			 /* 如果是取消父结点导致子结点取消，那么此时所有的子结点都应该是选择上的；
			  否则就是子结点取消导致父结点取消，然后父结点取消导致需要取消子结点，但
			  是这时候是不需要取消子结点的。*/
            if (children != null) {
                int index = 0;
                for (; index < children.size(); ++index) {
                    CheckBoxTreeNode childNode = (CheckBoxTreeNode) children.get(index);
                    if (!childNode.isSelected()) {
                        break;
                    }
                }
                // 从上向下取消的时候
                if (index == children.size()) {
                    for (Object child : children) {
                        CheckBoxTreeNode node = (CheckBoxTreeNode) child;
                        if (node.isSelected()) {
                            node.setSelected(false);
                        }
                    }
                }
            }

            // 向上取消，只要存在一个子节点不是选上的，那么父节点就不应该被选上。
            //这一块注释之后，子节点的取消不会影响父节点的勾选，为实现取消子节点，单独只选择父节点自己查看
            CheckBoxTreeNode pNode = (CheckBoxTreeNode) parent;
            if (pNode != null) {
                boolean hasChildChecked = false;
                Vector<TreeNode> siblings = pNode.children;
                for (TreeNode treeNode : siblings) {
                    CheckBoxTreeNode sibling = (CheckBoxTreeNode)treeNode;
                    if (sibling.isSelected()){
                        hasChildChecked = true;
                        break;
                    }
                }

                pNode.setSelected(hasChildChecked);
                pNode.childrenAllSelected = false;
            }
        }
    }

    public List<CheckBoxTreeNode> getAllSelectNodes() {
        List<CheckBoxTreeNode> list = new ArrayList<>();
        if (selected) {
            list.add(this);
        }
        if (children != null) {
            for (Object child : children) {
                if (child instanceof CheckBoxTreeNode) {
                    CheckBoxTreeNode node = (CheckBoxTreeNode) child;
                    list.addAll(node.getAllSelectNodes());
                }
            }
        }
        return list;
    }

    @Override
    public String toString() {
        if (userObject == null) {
            return "";
        }
        if (userObject instanceof File) {
            return ((File) userObject).getName();
        } else {
            return userObject.toString();
        }
    }

    public boolean isChildrenAllSelected() {
        return childrenAllSelected;
    }

    public void setChildrenAllSelected(boolean childrenAllSelected) {
        this.childrenAllSelected = childrenAllSelected;
    }
}
